﻿#include"XQTablePagingWidget.h"
#include"XQComboCheckButton.h"
#include"XQuickSort.hpp"
#include"XQAlgorithm.h"
#include"XQFuncEvent.h"
#include"XQTableExportWidget.h"
#include<set>
#include<QThread>
#include<QMenu>
#include<QTableWidget>
#include<QHeaderView>
#include<QLabel>
#include<QSpinBox>
#include<QComboBox>
#include<QApplication>
#include<QClipboard>
#include<QTimer>
#include<QDebug>
XQTablePagingWidget::XQTablePagingWidget(QWidget* parent, bool AutoInit)
	:QWidget(parent)
{
	if(AutoInit)
		init();
}

XQTablePagingWidget::~XQTablePagingWidget()
{
}

QList<XQTablePagingItem>& XQTablePagingWidget::datas()
{
	return m_data;
}

const QList<XQTablePagingItem>& XQTablePagingWidget::datas() const
{
	return m_data;
}

const QList<XQTablePagingItem>& XQTablePagingWidget::showDatas() const
{
	return *m_showData;
}

XQComboCheckButton* XQTablePagingWidget::findButton() const
{
	return m_findBtn;
}

XQComboCheckButton* XQTablePagingWidget::filterButton() const
{
	return m_filterBtn;
}

QTableWidget* XQTablePagingWidget::tableWidget() const
{
	return m_tableWidget;
}

QStringList XQTablePagingWidget::horizontalTitle()const
{
	// 获取包括被隐藏列的所有水平标题
	QStringList headerTexts;
	for (int column = 0; column < m_tableWidget->model()->columnCount(); ++column) {
		QString headerText = m_tableWidget->model()->headerData(column, Qt::Horizontal).toString();
		headerTexts.append(headerText);
	}

	return std::move(headerTexts);
}

bool XQTablePagingWidget::isSortBeing() const
{
	return m_sortBeing;
}

int XQTablePagingWidget::columnCount() const
{
	return m_tableWidget->columnCount();
}

size_t XQTablePagingWidget::dataSize()
{
	QReadLocker lock(&m_lock);
	return m_data.size();
}

QBoxLayout::Direction XQTablePagingWidget::direction() const
{
	return ((QBoxLayout*)this->layout())->direction();
}

QReadWriteLock* XQTablePagingWidget::dataLock() 
{
	return &m_lock;
}

void XQTablePagingWidget::push_backRow(const QStringList& text)
{
	XQTablePagingItem list;
	for (auto& t: text)
	{
		list << t;
	}
	push_backRow(list);
}

void XQTablePagingWidget::push_backRow(const XQTablePagingItem& data)
{
	QWriteLocker lock(&m_lock);
	m_data.append(data);
	if (m_updataBox->currentData().toInt() != 0)
		new XQFuncEvent(this, [=] {if (!m_updataTimer->isActive())m_updataTimer->start(); });
	emit dataCountChange(m_data.size());
}

void XQTablePagingWidget::push_backRow(XQTablePagingItem&& data)
{
	QWriteLocker lock(&m_lock);
	m_data.append(std::move(data));
	if (m_updataBox->currentData().toInt() != 0)
		new XQFuncEvent(this, [=] {if (!m_updataTimer->isActive())m_updataTimer->start(); });
	emit dataCountChange(m_data.size());
}

void XQTablePagingWidget::push_frontRow(const QStringList& text)
{
	XQTablePagingItem list;
	for (auto& t : text)
	{
		list << t;
	}
	push_frontRow(list);
}

void XQTablePagingWidget::push_frontRow(const XQTablePagingItem& data)
{
	QWriteLocker lock(&m_lock);
	m_data.push_front(data);
	if (m_updataBox->currentData().toInt() != 0)
		new XQFuncEvent(this, [=] {if (!m_updataTimer->isActive())m_updataTimer->start(); });
	emit dataCountChange(m_data.size());
}

void XQTablePagingWidget::push_frontRow(XQTablePagingItem&& data)
{
	QWriteLocker lock(&m_lock);
	m_data.push_front(std::move(data));
	if (m_updataBox->currentData().toInt() != 0)
		new XQFuncEvent(this, [=] {if (!m_updataTimer->isActive())m_updataTimer->start(); });
	emit dataCountChange(m_data.size());
}

void XQTablePagingWidget::pop_frontRow()
{
	QWriteLocker lock(&m_lock);
	m_data.pop_front();
}

void XQTablePagingWidget::pop_backRow()
{
	QWriteLocker lock(&m_lock);
	m_data.pop_back();
}

void XQTablePagingWidget::clearData()
{
	QWriteLocker lock(&m_lock);
	m_data.clear();
	new XQFuncEvent(this, [=] {m_updataTimer->stop(); });
	emit dataCountChange(m_data.size());
}

void XQTablePagingWidget::showDataAll()
{
	m_showData = &m_data;
	init_PagingUI(m_data.count());
	showTable();
}

void XQTablePagingWidget::showFilterData()
{
	m_showData = &m_filterData;
	init_PagingUI(m_filterData.count());
	updataTable();
}

void XQTablePagingWidget::showSearchData()
{
	m_showData = &m_SearchData;
	init_PagingUI(m_SearchData.count());
	updataTable();
}

void XQTablePagingWidget::showTable(int n)
{
	int nSel = n;//当前的页数
	int onePageCount = rowNumber();//当前一页能显示的数量
	if (n <= 0)
		nSel = m_paging->value();
	if (onePageCount == 0 || (n != -1 &&onePageCount == m_onePageCount && m_nSel == nSel && m_tableWidget->rowCount() == onePageCount))
		return; 
	m_nSel = nSel;
	m_onePageCount = onePageCount;
	clearTable();
	size_t start = (nSel - 1) * m_onePageCount;
	//int columnNumber = m_tableWidget->columnCount();//列数
	m_tableWidget->clearContents();//清空
	QReadLocker lock(&m_lock);
	for (size_t i = start; i < start+ m_onePageCount&&i< m_showData->count(); i++)
	{
		m_tableWidget->insertRow(i - start);
		auto& TableItem = (*m_showData)[i];
		for (size_t j = 0; j < TableItem.size(); j++)
		{
			auto item = new QTableWidgetItem(TableItem[j].first);
			item->setData(TABLEDATA, TableItem[j].second);
			m_tableWidget->setItem(i- start, j, item);
			/*if (j == 0)
			{
				item->setData();
			}*/
		}
		//设置水平标题序号
		m_tableWidget->setVerticalHeaderItem(i - start, new QTableWidgetItem(QString::number(i+1)));
	}
	// 调整列宽
	m_tableWidget->resizeColumnsToContents();
}

void XQTablePagingWidget::updataTable()
{
	init_PagingUI(m_data.count());
	//0:保持原先的索引 -1强制刷新 
	showTable(-1);
	new XQFuncEvent(this, [=] {m_updataTimer->stop(); });
	/*m_tableWidget->hide();
	m_tableWidget->show();*/
}

void XQTablePagingWidget::findSearch()
{
	auto str = m_findEdit->currentText();//待搜索文本
	if (str.isEmpty())
	{
		showDataAll();//显示的全部文本数据
		return;
	}
	m_SearchData.clear();//清空搜索的数据
	auto checkeds=m_findBtn->selectIndexs();//我选中了那几个标签要搜索
	auto* data = &m_data;
	if (!m_filterData.isEmpty())
		data = &m_filterData;
	for (auto& texts: *data)
	{
		for (auto&i: checkeds)
		{
			if (texts[i].first.indexOf(str) != -1)//匹配到一个
			{
				m_SearchData << texts;
				break;
			}
		}
	}
	showSearchData();//显示搜索到的结果
	//插入搜索记录
	if (m_findEdit->findText(str) == -1)
		m_findEdit->addItem(str);
}

void XQTablePagingWidget::filter()
{
	m_filterData.clear();
	auto checkeds = m_filterBtn->selectIndexs();//我选中了那几个标签要搜索
	for (auto& texts : m_data)
	{
		for (auto& i : checkeds)
		{
			if (m_filterMap_func[i](texts))//匹配到一个
			{
				m_filterData << texts;
				break;
			}
		}
	}
	showFilterData();
}

void XQTablePagingWidget::filter(std::function<bool(const XQTablePagingItem&)> func)
{
	m_filterData.clear();
	for (auto& texts : m_data)
	{
		if (func(texts))//匹配到一个
		{
			m_filterData << texts;
		}
	}
	showFilterData();
}

void XQTablePagingWidget::clearTable()
{
	int rowCount = m_tableWidget->rowCount();
	for (size_t i = 0; i < rowCount; i++)
	{
		m_tableWidget->removeRow(0);
	}
}

void XQTablePagingWidget::setCount(size_t count)
{
	m_count->setText(QString("数量:%1").arg(count));
}

void XQTablePagingWidget::setPages(size_t count)
{
	m_Pages->setText(QString("页数:%1").arg(count));
}

void XQTablePagingWidget::setTableUpdataTime(int sec)
{
	if(sec< m_updataBox->count())
		m_updataBox->setCurrentIndex(sec);
}

void XQTablePagingWidget::setSortFunc(int nSel, std::function<bool(const QPair<QString, QVariant>&, const QPair<QString, QVariant>&)> sort)
{
	if (nSel >= m_sortFunc.size())
		return;
		m_sortFunc[nSel] = sort;
}

void XQTablePagingWidget::addFilter(const QString& name, std::function<bool(const XQTablePagingItem&)> func, bool on)
{
	if (m_filterMap_nSel.find(name) != m_filterMap_nSel.end())
		return;
	auto nSel = m_filterBtn->addItem(name,on);
	m_filterMap_nSel[name] = nSel;
	m_filterMap_func[nSel] = func;
	m_filterBtn->show();
}

void XQTablePagingWidget::clearFilter()
{
	m_filterBtn->clear();
	m_filterMap_nSel.clear();
	m_filterMap_func.clear();
	m_filterBtn->hide();
}

void XQTablePagingWidget::reverse(QList<XQTablePagingItem>* data)
{
	if (data == nullptr)
		return;
	QWriteLocker lock(&m_lock);
	m_sortBeing = true;
	emit sortStart();
	std::reverse(data->begin(), data->end());
	m_sortBeing = false;
	emit sortFinish();
}

void XQTablePagingWidget::reverse()
{
	reverse(m_showData);
}

void XQTablePagingWidget::sort(int nSel)
{
	auto data = m_showData;
	bool& flag = m_sortFlag[nSel];
	auto& _sort = m_sortFunc[nSel];
	if (data == nullptr)
		return;

	auto isType = [](const QPair<QString,QVariant>& front, const QPair<QString, QVariant>& later,int type) {
		return front.second.type() == type && later.second.type() == type;
	};

	//排序方法
	auto method = [=](const XQTablePagingItem& frontList, const XQTablePagingItem& laterList)->bool {
		auto& front = frontList[nSel];
		auto& later = laterList[nSel];
		
		bool resul;
		if (_sort == nullptr)
		{
			if (isType(front, later, QVariant::Double))
				resul = front.second.toDouble() < later.second.toDouble();
			else if (isType(front, later, QVariant::Char))
				resul = front.second.toChar() < later.second.toChar();
			else if (isType(front, later, QVariant::UInt))
				resul = front.second.toUInt() < later.second.toUInt();
			else if (isType(front, later, QVariant::Int))
				resul = front.second.toInt() < later.second.toInt();
			else if (isType(front, later, QVariant::LongLong))
				resul = front.second.toLongLong() < later.second.toLongLong();
			else if (isType(front, later, QVariant::ULongLong))
				resul = front.second.toULongLong() < later.second.toULongLong();
			else
				resul = (QString::compare(front.first, later.first, Qt::CaseInsensitive) > 0) ? true : false;
		}
		else
		{
			resul = _sort(front, later);
		}
		if (!flag)
			resul = !resul;
		return resul;
	};
	//结束处理的函数
	auto finished = [=] 
	{
		new XQFuncEvent(this, [=] {//异步发送
		m_tableWidget->horizontalHeader()->setEnabled(true);
		updataTable();
		m_sortBeing = false;
		emit sortFinish();
		});
		m_sortFlag[nSel] = !flag; 
	};
	//if(m_threadPool==nullptr)
	{
		auto run = QThread::create([=] {
			QWriteLocker lock(&m_lock);
			XQuickSort(data->begin(), data->end(), method);
			finished();
			});
		//运行结束处理
		connect(run, &QThread::finished, run, &QThread::deleteLater);
		run->start();
	}

	//运行前处理
	m_tableWidget->horizontalHeader()->setEnabled(false);
	m_sortBeing = true;
	emit sortStart();
}

void XQTablePagingWidget::setDirection(QBoxLayout::Direction direction)
{
	
	QBoxLayout* layout =(QBoxLayout*)this->layout();
	QBoxLayout* m_functionLayout = (QBoxLayout*)m_paletteWidget->layout();
	layout->setDirection(direction);
	if (direction == QBoxLayout::TopToBottom|| direction == QBoxLayout::BottomToTop)
	{
		m_functionLayout->setDirection(QBoxLayout::LeftToRight);
	}
	else if (direction == QBoxLayout::LeftToRight || direction == QBoxLayout::RightToLeft)
	{
		m_functionLayout->setDirection(QBoxLayout::TopToBottom);
	}
}

void XQTablePagingWidget::setPaletteVisible(bool Visible)
{
	m_paletteWidget->setVisible(Visible);
}

void XQTablePagingWidget::setContextMenuFunc(std::function<void()> contextMenuFunc)
{
	m_contextMenuFunc = contextMenuFunc;
}

void XQTablePagingWidget::setContextMenuFunc()
{
	auto func = [=] {
		QMenu* menu = new QMenu(this);
		menu->setAttribute(Qt::WA_DeleteOnClose);
		menuAddDefaultMenu(menu);
		menu->popup(QCursor::pos());
	};
	setContextMenuFunc(func);
}

void XQTablePagingWidget::menuAddDefaultMenu(QMenu* menu)
{
	if (menu == nullptr)
		return;
	menuAddColumnHidden(menu);
	menuAddShowPalette(menu);
	if (m_paletteWidget->isVisible())
		menuAddDirection(menu);
	menu->addSeparator();
	menuAddCopy(menu);
	menuAddExport(menu);
}

void XQTablePagingWidget::menuAddColumnHidden(QMenu* mainMenu)
{
	QMenu* menu = new QMenu("隐藏显示列", mainMenu);
	mainMenu->addMenu(menu);
	auto titles = horizontalTitle();
	for (int i=0;i<titles.size();i++)
	{
		auto& title = titles[i];
		bool Hide = m_tableWidget->isColumnHidden(i);
		menu->addAction((Hide ? "显示<" : "隐藏<") + title + ">", [=]{
				m_tableWidget->setColumnHidden(i,!Hide);
			});
	}
	menu->addSeparator();
	menu->addAction("显示全部", [=]{
			for (int i = 0; i < titles.size(); i++)
			m_tableWidget->setColumnHidden(i, false);
		});
	menu->addAction("隐藏全部", [=] {
		for (int i = 0; i < titles.size(); i++)
			m_tableWidget->setColumnHidden(i, true);
		});
}

void XQTablePagingWidget::menuAddShowPalette(QMenu* menu)
{
	if (m_paletteWidget->isVisible())
		menu->addAction("隐藏功能栏", [=] {m_paletteWidget->setVisible(false); });
	else 
		menu->addAction("显示功能栏", [=] {m_paletteWidget->setVisible(true); });
}

void XQTablePagingWidget::menuAddDirection(QMenu* mainMenu)
{
	QMenu* menu = new QMenu("设置功能栏方向",mainMenu);
	mainMenu->addMenu(menu);
	auto dir = direction();
	if(dir!= QBoxLayout::LeftToRight)
		menu->addAction("左边", [=] {setDirection(QBoxLayout::LeftToRight); });
	if (dir != QBoxLayout::RightToLeft)
		menu->addAction("右边", [=] {setDirection(QBoxLayout::RightToLeft); });
	if (dir != QBoxLayout::TopToBottom)
		menu->addAction("上边", [=] {setDirection(QBoxLayout::TopToBottom); });
	if (dir != QBoxLayout::BottomToTop)
		menu->addAction("下边", [=] {setDirection(QBoxLayout::BottomToTop); });
}

void XQTablePagingWidget::menuAddExport(QMenu* menu)
{
	if (menu == nullptr)
		return;
	menu->addAction("导出到本地", [=] {
		//创建
		if(m_exportWidget==nullptr)
		{
			m_exportWidget = new XQTableExportWidget();
			m_exportWidget->setTableView(m_tableWidget);
			m_exportWidget->setExportData(m_showData);
			connect(m_exportWidget, &QWidget::destroyed, [=] {m_exportWidget = nullptr; });
			connect(this, &QWidget::destroyed, m_exportWidget, &QWidget::deleteLater);
		}
		//显示
		centerShow(m_exportWidget,this);
		});
}

void XQTablePagingWidget::menuAddCopy(QMenu* menu)
{
	if (menu == nullptr)
		return;
	menu->addAction("复制到剪切板", [=] { 
		auto items=m_tableWidget->selectedItems();
		QMap<int,std::set<int>> selectItem;//行-列 
		for (auto& item:items)
		{
			selectItem[item->row()].insert(item->column());
		}
		QString text;
		for (auto it= selectItem.begin();it!= selectItem.end();it++)
		{
			int row = it.key();
			for (auto& column :it.value())
			{
				text +=m_tableWidget->item(row, column)->text();
				text += "\t";
			}
			text.remove(text.size() - 1, 1);//删除最后一个\t
			text += "\r\n";
		}
		text.remove(text.size() - 2, 2);//删除最后一个\r\n
		QClipboard* clipboard = QApplication::clipboard();
		// 将文本复制到剪贴板
		clipboard->setText(text);
		});
}

void XQTablePagingWidget::setHorizontalTitle(const QStringList& title)
{
	m_findBtn->clear();
	m_findBtn->addItem(title,true);
	m_tableWidget->setColumnCount(title.count());
	m_tableWidget->setHorizontalHeaderLabels(title);
	m_sortFlag.resize(title.size());
	m_sortFunc.resize(title.size());
}
int XQTablePagingWidget::rowNumber()
{
	/*qInfo() << m_tableWidget->viewport()->height();*/
	//qInfo() << m_tableWidget->verticalHeader()->defaultSectionSize();
	int row = m_tableWidget->rowHeight(0);
	if (row == 0)
		row= m_tableWidget->verticalHeader()->defaultSectionSize();
	return m_tableWidget->viewport()->height() / row;
}

void XQTablePagingWidget::init_PagingUI(size_t count)
{
	int onePage = rowNumber();//一页数量
	if(onePage!=0&& count!=0)
	{
		int pageCount = count / onePage + (count % onePage == 0 ? 0 : 1);//页数
		setCount(count);
		setPages(pageCount);
		m_paging->setRange(1, pageCount);
	}
	else
	{
		setCount(0);
		setPages(0);
		m_paging->setRange(0, 0);
	}
}
